﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.WebControls;

namespace EnhancedCQWP.EnhancedContentQuery
{
    public partial class EnhancedContentQueryUserControl : UserControl
    {
        public string[] ContentTypes { get; set; }
        public string[] ContentTypeProperties { get; set; }
        public string[] ExtraSites { get; set; }
        public string XsltLink { get; set; }

        string ExpandParam
        {
            get
            {
                if (Request.QueryString["expandParam"] != null)
                {
                    return Request.QueryString["expandParam"];
                }
                return string.Empty;
            }
        }

        public string[] Sites
        {
            get
            {
                return ((EnhancedContentQuery)Parent)
                    .Sites
                    .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
                    .Concat(ExtraSites)
                    .ToArray();
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            try
            {
                if (Sites.Length == 0)
                {
                    writer.Write("No sites selected. Open the edit pane to select some sites.");
                }
                else
                {
                    var pages = GetPages(ContentTypes);
                    var doc = GenerateXml(pages);
                    var xml = doc.InnerXml;
                    var xslt = CmsDataFormWebPart.GetXslFile(XsltLink).OuterXml;
                    var transfomer = new XmlToXsltTransformer();
                    var html = transfomer.GetHtml(xml, xslt);
                    writer.Write(html); 
                }
            }
            catch (Exception ex)
            {
                Response.Write("Exception: " + ex.Message);
            }
        }

        private IEnumerable<PublishingPage> GetPages(string[] contentTypes)
        {


            var pages = new List<PublishingPage>();
            foreach (var siteUrl in Sites)
            {
                SPSite siteCollection = SPContext.Current.Site;
                using (var web = siteCollection.OpenWeb(siteUrl))
                {
                    if (web.DoesUserHavePermissions(SPBasePermissions.ViewPages))
                    {
                        var publishingWeb = PublishingWeb.GetPublishingWeb(web);

                        foreach (var contentType in contentTypes)
                        {
                            var pagesFromThisWeb = PagesFromThisContentType(contentType, publishingWeb);
                            var pagesToAdd = pagesFromThisWeb.Where(p => !pages.Select(pp => pp.Url).Contains(p.Url)).ToList();
                            pages.AddRange(pagesToAdd);
                        }
                    }
                }
            }
            return pages;
        }

        private static IEnumerable<PublishingPage> PagesFromThisContentType(string contentType, PublishingWeb publishingWeb)
        {
            var format = String.Format(@"<Where><Eq><FieldRef Name='ContentType'/><Value Type='Text'>{0}</Value></Eq></Where>", contentType);
            var query = new SPQuery { Query = format };
            var pagesFromThisWeb = publishingWeb.GetPublishingPages(query).ToList();
            return pagesFromThisWeb;
        }

        private XmlDocument GenerateXml(IEnumerable<PublishingPage> pages)
        {
            var doc = new XmlDocument();
            var dec = doc.CreateXmlDeclaration("1.0", null, null);
            doc.AppendChild(dec);
            var root = doc.CreateElement("Pages");
            root.SetAttribute("ExpandParam", ExpandParam);

            foreach (var page in pages)
            {
                var el = doc.CreateElement("Page");
                el.SetAttribute("LastModifiedDate", page.LastModifiedDate.ToString());
                el.SetAttribute("LastModifiedDateYear", page.LastModifiedDate.Year.ToString());
                el.SetAttribute("CreatedDate", page.CreatedDate.ToString());
                el.SetAttribute("AbsolutePath", page.Uri.AbsolutePath);
                el.SetAttribute("Title", page.Title);

                foreach (var property in ContentTypeProperties)
                {
                    if (page.ListItem.Properties[property] != null)
                    {
                        el.SetAttribute(property, page.ListItem.Properties[property].ToString());
                    }
                    else if (page.ListItem.Fields.ContainsField(property) && page.ListItem[property] != null)
                    {
                        el.SetAttribute(property, page.ListItem[property].ToString());
                    }
                }
                root.AppendChild(el);
            }
            doc.AppendChild(root);

            return doc;
        }
    }
}
